/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.restassured.itest.java;
import com.github.fge.jsonschema.cfg.ValidationConfiguration;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import io.restassured.itest.java.support.WithJetty;
import io.restassured.module.jsv.JsonSchemaValidator;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import static com.github.fge.jsonschema.SchemaVersion.DRAFTV3;
import static com.github.fge.jsonschema.SchemaVersion.DRAFTV4;
import static io.restassured.RestAssured.*;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchema;
import static io.restassured.module.jsv.JsonSchemaValidatorSettings.settings;
import static org.hamcrest.Matchers.*;
public class JsonSchemaValidationITest extends WithJetty {
@Test public void
matches_string_schema_correctly() throws IOException {
// Given
String schema = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("products-schema.json"));
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchema(schema));
}
@Test public void
matches_input_stream_schema_correctly() throws IOException {
// Given
InputStream schema = Thread.currentThread().getContextClassLoader().getResourceAsStream("products-schema.json");
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchema(schema));
}
@Test public void
matches_classpath_schema_correctly() throws IOException {
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json"));
}
@Test public void
works_with_expectation_api() throws IOException {
// When
expect().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json")).when().get("/products");
}
@Test public void
can_mix_json_schema_validation_and_body_validations() throws IOException {
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json")).and().body("[0].name", equalTo("An ice sculpture"));
}
@Test public void
throws_assertion_error_when_schema_doesnt_match_json_content() throws IOException {
exception.expect(AssertionError.class);
exception.expectMessage("The content to match the given JSON schema.\n" +
"error: instance type (object) does not match any allowed primitive type (allowed: [\"array\"])\n" +
" level: \"error\"\n" +
" schema: {\"loadingURI\":\"#\",\"pointer\":\"\"}\n" +
" instance: {\"pointer\":\"\"}\n" +
" domain: \"validation\"\n" +
" keyword: \"type\"\n" +
" found: \"object\"\n" +
" expected: [\"array\"]\n" +
"\n" +
" Actual: { \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95 }\n" +
" }\n" +
"}");
// When
get("/jsonStore").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json").using(settings().parseUriAndUrlsAsJsonNode(true)));
}
@Test public void
json_schema_validator_supports_disabling_checked_validation_statically() {
// Given
JsonSchemaValidator.settings = settings().with().checkedValidation(false);
// When
try {
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json"));
} finally {
JsonSchemaValidator.reset();
}
}
@Test public void
json_schema_validator_supports_specifying_json_schema_factory_instance_statically() {
// Given
JsonSchemaValidator.settings = settings().with().jsonSchemaFactory(
JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV3).freeze()).freeze());
// When
try {
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json"));
} finally {
JsonSchemaValidator.reset();
}
}
@Test public void
json_schema_validator_supports_specifying_json_schema_factory_instance_and_disabling_checked_validation_statically() {
// Given
JsonSchemaValidator.settings = settings().with().jsonSchemaFactory(
JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV3).freeze()).freeze()).
and().with().checkedValidation(false);
// When
try {
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json"));
} finally {
JsonSchemaValidator.reset();
}
}
@Test public void
json_schema_validator_supports_using_a_supplied_json_schema_factory_instance() {
// Given
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV4).freeze()).freeze();
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json").using(jsonSchemaFactory));
}
@Test public void
json_schema_validator_supports_using_the_supplied_json_schema_validator_settings() {
// When
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("products-schema.json").using(settings().with().checkedValidation(false)));
}
@Test public void
json_schema_validator_supports_draft_03() {
// when
get("/jsonStore").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("store-schema.json"));
}
@Test public void
json_schema_validator_supports_draft_03_failures() {
exception.expect(AssertionError.class);
exception.expectMessage(allOf(containsString("Response body doesn't match expectation.\n" +
"Expected: The content to match the given JSON schema.\n" +
"error: object has missing required properties ([\"isbn\"])\n" +
" level: \"error\"\n" +
" schema: {\"loadingURI\":\"file:"),
containsString("store-schema-isbn-required.json#\",\"pointer\":\"/properties/store/properties/book/items/1\"}\n" +
" instance: {\"pointer\":\"/store/book/1\"}\n" +
" domain: \"validation\"\n" +
" keyword: \"properties\"\n" +
" required: [\"isbn\"]\n" +
" missing: [\"isbn\"]\n" +
"\n" +
" Actual: { \"store\": {\n" +
" \"book\": [ \n" +
" { \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" { \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95 }\n" +
" }\n" +
"}")));
// when
get("/jsonStore").then().assertThat().body(JsonSchemaValidator.matchesJsonSchemaInClasspath("store-schema-isbn-required.json"));
}
@Test public void
greet_json_resource_conforms_to_the_greeting_schema() {
given().
param("firstName", "John").
param("lastName", "Doe").
when().
get("/greetJSON").
then().
body(JsonSchemaValidator.matchesJsonSchemaInClasspath("greeting-schema.json"));
}
@Test public void
json_schema_validator_supports_matching_uri_json_schema_as_json_node() throws Exception {
// Given
String schema = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("products-schema.json"));
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setResponseCode(200).setBody(schema));
server.play();
try {
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchema(new URI("http://localhost:"+server.getPort())).using(settings().parseUriAndUrlsAsJsonNode(true)));
} finally {
server.shutdown();
}
}
@Test public void
json_schema_validator_supports_matching_uri_json_schema_as_string_to_uri() throws Exception {
// Given
String schema = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("products-schema.json"));
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setResponseCode(200).setBody(schema));
server.play();
try {
get("/products").then().assertThat().body(JsonSchemaValidator.matchesJsonSchema(new URI("http://localhost:"+server.getPort())).using(settings().parseUriAndUrlsAsJsonNode(false)));
} finally {
server.shutdown();
}
}
}